﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Net.Mime;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace DriveBeamEditor.Controls.General
{
    [Designer(typeof(CollapsibleControlListDesigner))]
    public partial class CollapsibleControlList : UserControl
    {
        #region Fields

        private bool _busy = false;

        private bool _autoCollapseOthersOnExpand = true;
        private bool _allowExpandAndCollapseAll = true;
        private bool _useSharedGroupAppearance = true;

        private Color _groupForeColor = Color.FromArgb(255, 108, 0);
        private Font _groupFont = new Font("Arial Rounded MT", 8.25f, FontStyle.Bold, GraphicsUnit.Pixel);
        private Theme _groupButtonsTheme = Theme.MSOffice2010_RED;

        #endregion

        #region Properties

        [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
        public Panel DropZone
        {
            get { return dropZone; }
        }

        /// <summary>Gets or sets a value indicating whether expanding a group should collapse others</summary>
        public bool AutoCollapseOthersOnExpand
        {
            get { return _autoCollapseOthersOnExpand; }
            set
            {
                _autoCollapseOthersOnExpand = value;
                if (value)
                    CollapseAllButOne(dropZone.Controls.OfType<CollapsibleBox>().FirstOrDefault(box => !box.IsCollapsed));
            }
        }

        /// <summary>Gets or sets whether user should be able to expand or collapse all</summary>
        public bool AlowExpandAndCollapseAll
        {
            get { return _allowExpandAndCollapseAll; }
            set
            {
                _allowExpandAndCollapseAll = value;
                UpdateButtonsUI();
            }
        }

        public bool UseSharedGroupAppearance
        {
            get { return _useSharedGroupAppearance; }
            set
            {
                _useSharedGroupAppearance = value;
                if (value)
                    SetSharedGroupAppearance();
            }
        }

        /// <summary>Gets or sets a common fore color to use for all groups</summary>
        public Color GroupForeColor
        {
            get { return _groupForeColor; }
            set
            {
                _groupForeColor = value;
                if (_useSharedGroupAppearance)
                    SetSharedGroupAppearance();
            }
        }


        /// <summary>Gets or sets a common font to use for all groups</summary>
        public Font GroupFont
        {
            get { return _groupFont; }
            set
            {
                _groupFont = value;
                if (_useSharedGroupAppearance)
                    SetSharedGroupAppearance();
            }
        }

        public Theme GroupButtonsTheme
        {
            get { return _groupButtonsTheme; }
            set
            {
                _groupButtonsTheme = value;
                if(_useSharedGroupAppearance)
                    SetSharedGroupAppearance();
            }
        }

        [Browsable(true)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
        public override string Text
        {
            get { return box.Text; }
            set { box.Text = value; }
        }

        [Browsable(true)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
        public override Color ForeColor
        {
            get { return base.ForeColor; }
            set
            {
                base.ForeColor = value;
                box.ForeColor = value;
            }
        }

        [Browsable(true)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
        public override Font Font
        {
            get { return base.Font; }
            set
            {
                base.Font = value;
                box.Font = value;
            }
        }

        public Theme ButtonsTheme
        {
            get { return xbCollapseAll.Theme; }
            set { SetButtonsTheme(value); }
        }

        #endregion

        #region CTORs

        public CollapsibleControlList()
        {
            InitializeComponent();
        }

        #endregion

        #region Events

        private void xbExpandAll_Click(object sender, EventArgs e)
        {
            ExpandAll();
        }

        private void xbCollapseAll_Click(object sender, EventArgs e)
        {
            CollapseAll();
        }

        private void dropZone_SizeChanged(object sender, EventArgs e)
        {
            BestFitControls();
        }

        private void dropZone_Resize(object sender, EventArgs e)
        {
            BestFitControls();
        }

        private void dropZone_ControlAdded(object sender, ControlEventArgs e)
        {
            /* Only allow collapsible boxes */
            if (!(e.Control is CollapsibleBox))
            {
                if (DesignMode)
                {
                    MessageBox.Show(@"Please add only 'CollapsibleBox' controls to this.", @"Incomptatible control",
                        MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
                }
                BeginInvoke(new Action(() => dropZone.Controls.Remove(e.Control)));
                return;
            }

            /* Configure control */
            e.Control.Dock = DockStyle.Top;
            (e.Control as CollapsibleBox).Expanded += CollapsibleBox_Expanded;
            if (_useSharedGroupAppearance)
                SetSharedGroupAppearance(e.Control as CollapsibleBox);

            /* Adapt size limits */
            AdaptControlSizes(e.Control);
        }

        private void CollapsibleBox_Expanded(object sender, EventArgs e)
        {
            /* Prevent auto-collapse on 'Expand all' */
            if (_busy) return;

            CollapseAllButOne(sender as Control);
        }

        #endregion

        #region Methods

        private void UpdateButtonsUI()
        {
            xbCollapseAll.Visible = _allowExpandAndCollapseAll;
            xbExpandAll.Visible = _allowExpandAndCollapseAll;
        }

        private void SetButtonsTheme(Theme theme)
        {
            xbCollapseAll.Theme = theme;
            xbExpandAll.Theme = theme;
            xbCollapseAll.Invalidate();
            xbExpandAll.Invalidate();
        }

        public void BestFitControls()
        {
            foreach (var ctrl in dropZone.Controls.Cast<Control>())
            {
                AdaptControlSizes(ctrl);
            }
        }

        public void CollapseAll()
        {
            _busy = true;
            foreach (var cBox in dropZone.Controls.OfType<CollapsibleBox>())
            {
                cBox.Collapse();
            }
            _busy = false;
        }

        public void ExpandAll()
        {
            _busy = true;
            foreach (var cBox in dropZone.Controls.OfType<CollapsibleBox>())
            {
                cBox.Expand();
            }
            _busy = false;
        }

        public void CollapseAllButOne(Control ctrl)
        {
            foreach (var cBox in dropZone.Controls.OfType<CollapsibleBox>())
            {
                if (cBox != ctrl)
                    cBox.Collapse();
            }
        }

        private void AdaptControlSizes(Control ctrl)
        {
            ctrl.MinimumSize = new Size(dropZone.Width, ctrl.MinimumSize.Height);
            ctrl.MaximumSize = new Size(dropZone.Width, ctrl.MaximumSize.Height);
        }

        private void SetSharedGroupAppearance()
        {
            foreach (var cBox in dropZone.Controls.OfType<CollapsibleBox>())
            {
                SetSharedGroupAppearance(cBox);
            }
        }

        private void SetSharedGroupAppearance(CollapsibleBox ctrl)
        {
            ctrl.Font = _groupFont;
            ctrl.ForeColor = _groupForeColor;
            ctrl.ButtonsTheme = _groupButtonsTheme;
        }

        #endregion
    }
}
